/*
 * Copyright (c) 2009, Matt Labbe
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *           notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *           notice, this list of conditions and the following disclaimer in the
 *           documentation and/or other materials provided with the distribution.
 *     * Neither the name of the <organization> nor the
 *           names of its contributors may be used to endorse or promote products
 *           derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY MATT LABBE ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL MATT LABBE BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

function StopWatchAssistant() {
	/* this is the creator function for your scene assistant object. It will be passed all the 
	   additional parameters (after the scene name) that were passed to pushScene. The reference
	   to the scene controller (this.controller) has not be established yet, so any initialization
	   that needs the scene controller should be done in the setup function below. */
}

StopWatchAssistant.prototype.setup = function() {
	/* this function is for setup tasks that have to happen when the scene is first created */
	
	//set up application variables
	this.startTime = null; // start timing from this point
	this.stopTime = null; // time the stop button is pressed
	this.elapsedTime = 0; // the running count of time on the clock after stopping.
	this.interval = null; // holds function for updating the onscreen time
	this.running = false; // if the timer is currently running / convenience
	this.cookie = null; // stores timer state.
	this.splitListItems = []; //list of time splits (usually for laps)
	
	
	/* use Mojo.View.render to render view templates and add them to the scene, if needed. */
	
	/* setup widgets here */
	
	this.startButtonModel = { 
		buttonLabel : "Start",
		buttonClass : 'palm-button affirmative"',
		disabled : false		
	};

	this.stopButtonModel = { 
			buttonLabel : "Stop",
			buttonClass : 'palm-button negative"',
			disabled : false		
		};

	this.resetButtonModel = { 
			buttonLabel : "Reset",
			buttonClass : 'palm-button"',
			disabled : false		
		};

	this.splitButtonModel = { 
			buttonLabel : "Split",
			buttonClass : 'palm-button"',
			disabled : false		
		};	
	
	this.controller.setupWidget(
			"startButton",
			this.attributes = {disabledProperty: 'disabled'},
			this.model=this.startButtonModel
			);

	this.controller.setupWidget(
			"stopButton",
			this.attributes = {disabledProperty: 'disabled'},
			this.model=this.stopButtonModel
			);
	$("stopButton").hide();
	
	this.controller.setupWidget("resetButton",
			this.attributes = {disabledProperty: 'disabled'},
			this.model=this.resetButtonModel
			);

	this.controller.setupWidget("splitButton",
			this.attributes = {disabledProperty: 'disabled'},
			this.model=this.splitButtonModel
			);
	$("splitButton").hide();
	
	
	
	
	/* add event handlers to listen to events from widgets */
	Mojo.Event.listen(this.controller.get('startButton'),Mojo.Event.tap, this.startPressed.bind(this));
	Mojo.Event.listen(this.controller.get('stopButton'),Mojo.Event.tap, this.stopPressed.bind(this));
	Mojo.Event.listen(this.controller.get('resetButton'),Mojo.Event.tap, this.resetPressed.bind(this));
	Mojo.Event.listen(this.controller.get('splitButton'),Mojo.Event.tap, this.splitPressed.bind(this));
	

	/* load up the current state from cookies */
	this.cookie = new Mojo.Model.Cookie("StopWatchState");	
	var state = this.cookie.get();	 
	if (state) {
		if (state.splits)
		{
			this.splitListItems = state.splits;	
		}
		
		this.elapsedTime = state.elapsedTime;
		
		if (state.running == true) {
			this.startTime = new Date(state.startTime);
			this.startTiming(false);
		} else {
			this.startTime = null;
			this.displayTime();
		}
	
	}


	/* Split List Setup */
	this.controller.setupWidget("splitListWgt",
			this.splitListAttr = {
				itemTemplate: "stop-watch/splitListItem",
				listTemplate: "stop-watch/splitListTemplate",
				swipeToDelete: false,				
				reorderable: false,
				fixedHeightItems: true
			},
			this.splitListModel = {
				items: this.splitListItems
			}
	);
	
	// don't show the split list if 
	if (this.splitListItems.length == 0) {
		$("splitGroup").hide();
	}

	// set up the application dropdown menu
	this.controller.setupWidget(Mojo.Menu.appMenu, appMenuAttr, appMenuModel);

}

// Saves the application state to a cookie.
StopWatchAssistant.prototype.saveCookieState = function()
{
	this.cookie.put(
	{
		running: this.running,
		startTime: this.startTime.getTime(),
		elapsedTime: this.elapsedTime,
		splits: this.splitListItems
	}
	);		

}

// This is called when the start button is pressed
StopWatchAssistant.prototype.startPressed = function() {
	this.startTiming(true)
	this.saveCookieState();	

}

// this handles the start button logic
// if withNewTime is true, then a new startTime is created.
StopWatchAssistant.prototype.startTiming = function(withNewTime){
	
	if (withNewTime == true) {
		this.startTime = new Date();
	}
	
	$("startButton").hide();
	$("resetButton").hide();
	$("stopButton").show();
	$("splitButton").show();
	this.running = true;
	
	this.startInterval();
}

// sets the timer that updates the display
StopWatchAssistant.prototype.startInterval = function() {
	var scene = this;
	
	this.interval = window.setInterval(function () {
		scene.displayTime();
	}, 67);
	
}

// when the stop button is pressed
StopWatchAssistant.prototype.stopPressed = function() {
	this.stopTime = new Date();

	// clear mechanism that updates the time display.
	if (this.interval) {
		window.clearInterval(this.interval);
		this.interval = null;
	}	
	this.running = false;
	
	// elapsedTime is the time that was on the clock before the last start/stop.	
	this.elapsedTime = this.stopTime.getTime() - this.startTime.getTime() + this.elapsedTime;
	$("timerDisplay").innerHTML = this.processTime(this.elapsedTime);
		
	$("stopButton").hide();
	$("splitButton").hide();
	$("resetButton").show();
	$("startButton").show();

	this.saveCookieState();	
}

StopWatchAssistant.prototype.resetPressed = function() {
	this.elapsedTime = 0;

	$("timerDisplay").innerHTML = this.processTime(this.elapsedTime);
	
	// clear the split list
	this.splitListItems.length=0;
	this.controller.modelChanged(this.splitListModel, this);
	$("splitGroup").hide();

	this.saveCookieState();	
}

StopWatchAssistant.prototype.splitPressed = function() {

	// gets the count on the clock
	diff = this.displayTime();		

	// calculate the time between the last split taken, if there was one.	
	if (this.splitListItems.length > 0) {
		splitDiff = diff - this.splitListItems[0].time; 
	} else {
		splitDiff = 0;
	}
	
	// format the split difference time for display
	displaySplitDiff = this.processTime(splitDiff);
	
	// add the calculated values to the top of the split list
	this.splitListItems.unshift({number: this.splitListItems.length + 1, time: diff, displayTime: this.processTime(diff), splitDiff: displaySplitDiff});
	this.controller.modelChanged(this.splitListModel, this);
	
	$("splitGroup").show();

	this.saveCookieState();
}

// calculates the difference in the display
// TODO: pick a better name for the function.
StopWatchAssistant.prototype.displayTime = function() {
	var now, diff;

	if (this.startTime) // if we don't have a start time then we're not really running.
	{
		now = new Date();
		diff = now.getTime() - this.startTime.getTime() + this.elapsedTime;	
	} else { // since we're not running we only care about elapsedTime
		diff = this.elapsedTime;
	}
		
	$("timerDisplay").innerHTML = this.processTime(diff);
	
	return diff;
}

// takes the number of milliseconds and formats into a time suitable for display.
StopWatchAssistant.prototype.processTime= function(millisecs){
	var h, m, s, ms, hh, mm, ss, msms;
	h = Math.floor(millisecs / (60*60*1000)) ;
	m = Math.floor(millisecs / (60*1000)) % 60;
	s = Math.floor(millisecs / 1000) % 60;
	ms = millisecs % 1000;
	hh = "0" + h.toString();
	mm = "0" + m.toString();
	ss = "0" + s.toString();
	msms = "00" + ms.toString();
	hh = hh.substring(hh.length - 2);
	mm = mm.substring(mm.length - 2);
	ss = ss.substring(ss.length - 2);
	msms = msms.substring(msms.length - 3);
	return hh + ":" + mm + ":" + ss + ":" + msms ;	
	
}
StopWatchAssistant.prototype.activate = function(event) {
	/* put in event handlers here that should only be in effect when this scene is active. For
	   example, key handlers that are observing the document */
}


StopWatchAssistant.prototype.deactivate = function(event) {
	/* remove any event handlers you added in activate and do any other cleanup that should happen before
	   this scene is popped or another scene is pushed on top */
}

StopWatchAssistant.prototype.cleanup = function(event) {
	/* this function should do any cleanup needed before the scene is destroyed as 
	   a result of being popped off the scene stack */
}
